home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / netmgr.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  10KB  |  467 lines

  1. /* --------------------------------- netmgr.c ------------------------------- */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* Manage network ports (devices, cards, whatever you want to call these)
  8.  * Only one port is available on most machines.
  9. */
  10.  
  11. #include "fly.h"
  12.  
  13.  
  14. static NETPORT    *netports = 0;
  15. static int    nnetports = 0;
  16.  
  17. LOCAL_FUNC int NEAR
  18. packet_xmit (PACKET *pack, NETPORT *np)
  19. {
  20.     if ((np->NetDriver)->Send (np, pack)) {
  21.         if (pack)
  22.             ++STATS_NETERRSEND;
  23.         return (1);
  24.     }
  25.     if (pack) {
  26.         STATS_NETSENTBYTES += pack->length;
  27.         ++STATS_NETSENTPACKETS;
  28.     }
  29.     return (0);
  30. }
  31.  
  32. LOCAL_FUNC int NEAR
  33. netport_init (int n, char *ndname)
  34. {
  35.     NETPORT            *np;
  36.     struct NetDriver    NEAR* FAR* nd;
  37.     char            *options, *p;
  38.     int            nlen;
  39.     int            unit;
  40.     int            i;
  41.  
  42.     if (n >= nnetports) {
  43.         MsgEPrintf (-100, "netport: bad port %d", n);
  44.         return (1);
  45.     }
  46.  
  47.     if (!(nlen = strlen (ndname))) {
  48.         MsgEPrintf (-100, "netport: no name");
  49.         return (1);
  50.     }
  51.  
  52.     unit = 0;
  53.     options = strchr (ndname, '.');
  54.     if (options) {
  55.         nlen = options - ndname;
  56.         unit = options[1];
  57.         if (!nlen || !unit) {
  58.             MsgEPrintf (-100, "netport: bad name %s", ndname);
  59.             return (1);
  60.         }
  61.         options += 2;
  62.     } else
  63.         options = ndname;
  64.  
  65.     options = strchr (options, ':');
  66.     if (options) {
  67.         if (!nlen) {
  68.             nlen = options - ndname;
  69.             if (!nlen) {
  70.                 MsgEPrintf (-100, "netport: bad options %s",
  71.                     ndname);
  72.                 return (1);
  73.             }
  74.         }
  75.     }
  76.  
  77.     for (nd = NetDrivers; *nd; ++nd) {
  78.         if (!strnicmp ((*nd)->name, ndname, nlen) && !(*nd)->name[nlen])
  79.             break;
  80.     }
  81.     if (!(*nd)) {
  82.         MsgEPrintf (-100, "netport: unknown driver %s", ndname);
  83.         return (1);
  84.     }
  85.  
  86.     np = &netports[n];
  87.     np->flags = 0;
  88.     np->netport = n;
  89.     np->unit = (char)unit;
  90.     np->NetDriver = *nd;
  91.     np->incoming[HEAD] = np->incoming[TAIL] = 0;
  92.  
  93.     MsgPrintf (-100, "Netport  %s.%c", (*nd)->name, (int)np->unit);
  94.  
  95.     if ((*nd)->Init (np, options))
  96.         return (1);
  97.     np->flags |= NP_ON;
  98.     if (T(p = get_arg (options, "pack"))) {
  99.         np->flags |= NP_PACKING;
  100.         np->packlen = PAKPACKLEN;
  101.         if ('=' == *p) {
  102.             if (get_int (p+1, &i))
  103.                 MsgEPrintf (-100, "%s.%c bad 'pack' option",
  104.                         (*nd)->name, (int)np->unit);
  105.             else if (i > PAKPACKLEN)
  106.                 MsgEPrintf (-100, "%s.%c 'pack' too large",
  107.                         (*nd)->name, (int)np->unit);
  108.             else
  109.                 np->packlen = i;
  110.         }
  111.         MsgPrintf (-100, "%s.%c packing %d", (*nd)->name,
  112.                 (int)np->unit, (int)np->packlen);
  113.     }
  114.  
  115.     return (0);
  116. }
  117.  
  118. extern int FAR
  119. netports_init (void)
  120. {
  121.     int        n, i;
  122.     struct netname    *nn;
  123.  
  124.     for (n = 0, nn = st.netnames; nn; ++n, nn = nn->next)
  125.         ;
  126.  
  127.     if (!(netports = (NETPORT *) memory_calloc (n, sizeof (*netports)))) {
  128.         MsgEPrintf (-100, "netport: no mem");
  129.         return (1);
  130.     }
  131.     nnetports = n;
  132.  
  133.     for (i = 0, n = 0, nn = st.netnames; nn; ++n, nn = nn->next)
  134.         if (!netport_init (n, nn->name))
  135.             ++i;
  136.     if (!i) {
  137.         MsgEPrintf (-100, "netport: no active ports");
  138.         return (1);
  139.     }
  140.     return (0);
  141. }
  142.  
  143. LOCAL_FUNC void NEAR
  144. netport_term (int n)
  145. {
  146.     NETPORT        *np;
  147.     PACKET        *pack;
  148.  
  149.     np = &netports[n];
  150.     if (!(np->flags & NP_ON))
  151.         return;
  152.     if (np->outpak) {
  153.         if (np->outpak->length > 1)
  154.             packet_xmit (np->outpak, np);    /* flush packed */
  155.         packet_del (np->outpak);
  156.         np->outpak = 0;
  157.     }
  158.     (np->NetDriver)->Term (np);
  159.     np->flags = 0;
  160.     np->NetDriver = 0;
  161.  
  162.     for (pack = np->incoming[HEAD]; pack;)
  163.         pack = packet_del (pack);
  164.     np->incoming[HEAD] = np->incoming[TAIL] = 0;
  165.  
  166.     for (pack = np->outgoing; pack;)
  167.         pack = packet_del (pack);
  168.     np->outgoing = 0;
  169. }
  170.  
  171. extern void FAR
  172. netports_term (void)
  173. {
  174.     int    n;
  175.  
  176.     for (n = 0; n < nnetports; ++n)
  177.         netport_term (n);
  178.  
  179.     netports = memory_cfree (netports, nnetports, sizeof (*netports));
  180.     nnetports = 0;
  181. }
  182.  
  183. LOCAL_FUNC void NEAR
  184. packet_accept (PACKET *pack)
  185. {
  186.     PLAYER    *pl;
  187.     int    lcrc;
  188.  
  189.     ++STATS_NETRECEIVEDP;        /* count rcvd packet */
  190.     lcrc = (pack->raw[pack->length-2] << 8)
  191.               + pack->raw[pack->length-1];
  192.     if ((short)lcrc != (short)crc (pack)) {
  193.         packet_del (pack);
  194.         pack = 0;
  195.         ++STATS_NETERRCRC;
  196.     } else if (T(pl = player_active (pack))) {
  197.         pack->next = 0;
  198.         if (pl->tail)
  199.             pl->tail->next = pack;
  200.         else
  201.             pl->incoming = pack;
  202.         pl->tail = pack;
  203.     } else {
  204.         packet_del (pack);    /* oops, drop the packet */
  205.         pack = 0;
  206.         ++STATS_NETERRNOPLAYER;
  207.     }
  208. }
  209.  
  210. LOCAL_FUNC void NEAR
  211. packet_unpack (PACKET *packed)
  212. {
  213.     Uchar    *p;
  214.     PACKET    *pack;
  215.     int    l;
  216.     int    len;
  217.  
  218.     for (p = packed->raw + 1, l = packed->length - 1;
  219.                         l > 0; p += pack->length) {
  220.         len = ((int)p[0] << 8) + p[1];
  221.         p += 2;
  222.         l -= len + 2;
  223.         if (l < 0) {
  224.             ++STATS_NETERRPACKED;        /* bad packing */
  225.             break;
  226.         }
  227.         if (!(pack = packet_new (len, LADDRESS)))
  228.             break;                /* loose it */
  229.         pack->netport = packed->netport;    /* copy player's id */
  230.         pack->address = pack->raw - LADDRESS;
  231.         memcpy (pack->address, packed->address, LADDRESS);
  232.         pack->arrived = packed->arrived;
  233.         pack->length  = len;
  234.         memcpy (pack->raw, p, len);
  235.         packet_accept (pack);
  236.     }
  237.     packet_del (packed);
  238. }
  239.  
  240. LOCAL_FUNC void NEAR
  241. netport_receive (NETPORT *port)
  242. {
  243.     PACKET    *pack, *prev;
  244.     Ulong    iflags;
  245.  
  246.     if (port->NetDriver->Poll)
  247.         port->NetDriver->Poll (port);
  248.  
  249.     for (;;) {
  250.         iflags = Sys->Disable ();
  251.         if (T(pack = port->incoming[HEAD]) &&
  252.             F(port->incoming[HEAD] = pack->next))
  253.             port->incoming[TAIL] = 0;
  254.         Sys->Enable (iflags);
  255.         if (!pack)
  256.             break;
  257.         if (RC_PACKED == pack->raw[0])
  258.             packet_unpack (pack);
  259.         else
  260.             packet_accept (pack);
  261.     }
  262.  
  263.     for (prev = 0, pack = port->outgoing; pack;) {
  264.         if (RC_SENDOK == pack->raw[0])
  265.             ;
  266.         else if (RC_SENDFAIL == pack->raw[0])
  267.             ++STATS_NETERRSENDA;
  268.         else {            /* send pending */
  269.             prev = pack;
  270.             pack = pack->next;
  271.             continue;
  272.         }
  273.         if (prev)
  274.             prev->next = pack->next;
  275.         pack = packet_del (pack);
  276.     }
  277.     if (!prev)
  278.         port->outgoing = 0;
  279. }
  280.  
  281. extern void FAR
  282. netports_receive (void)
  283. {
  284.     NETPORT        *port;
  285.     int        i;
  286.  
  287.     for (i = 0, port = netports; i < nnetports; ++i, ++port) {
  288.         if (port->flags & NP_ON)
  289.             netport_receive (port);
  290.     }
  291. }
  292.  
  293. extern void FAR
  294. netports_poll (void)
  295. {
  296.     NETPORT        *port;
  297.     int        i;
  298.  
  299.     for (i = 0, port = netports; i < nnetports; ++i, ++port)
  300.         if ((port->flags & NP_ON) && port->NetDriver->Poll)
  301.             port->NetDriver->Poll (port);
  302. }
  303.  
  304. extern void FAR
  305. PlName (PLAYER *pl)
  306. {
  307.     memset (pl->name, 0, LNAME);
  308.     memset (pl->team, 0, LNAME);
  309. #if 1
  310.     sprintf (pl->name, "%02x%02x%02x",
  311.         pl->address[3], pl->address[4], pl->address[5]);
  312.     strncpy (pl->team, "[*]", LNAME);
  313. #else
  314.     NETPORT    *port;
  315.     char    unit[2];
  316.  
  317.     port = &netports[pl->netport];
  318.     if (!(port->flags & NP_ON))
  319.         return;
  320.     unit[0] = port->unit;
  321.     unit[1] = '\0';
  322.     strncpy (pl->name, port->NetDriver->name, LNAME);
  323.     strncat (pl->name, ".", LNAME);
  324.     strncat (pl->name, unit, LNAME);
  325. #endif
  326. }
  327.  
  328. extern void FAR
  329. netport_count (PLAYER *pl, int delta)
  330. {
  331.     NETPORT    *port;
  332.  
  333.     port = &netports[pl->netport];
  334.     if (!(port->flags & NP_ON))
  335.         return;
  336.     port->nplayers += delta;
  337. }
  338.  
  339. extern int FAR
  340. packet_deliver (PACKET *pack)
  341. {
  342.     NETPORT    *port;
  343.     Ulong    iflags;
  344.  
  345.     port = &netports[pack->netport];
  346.     if (!(port->flags & NP_ON)) {
  347.         packet_del (pack);
  348.         return (1);
  349.     }
  350.     pack->flags = 0;
  351.     pack->next = 0;
  352.     pack->arrived = st.lasttime;
  353.  
  354.     iflags = Sys->Disable ();
  355.     if (port->incoming[TAIL])
  356.         port->incoming[TAIL]->next = pack;
  357.     else
  358.         port->incoming[HEAD] = pack;
  359.     port->incoming[TAIL] = pack;
  360.     Sys->Enable (iflags);
  361.  
  362.     STATS_NETRECEIVEDBYTES += pack->length;
  363.     ++STATS_NETRECEIVEDPACKETS;
  364.     return (0);
  365. }
  366.  
  367. LOCAL_FUNC int NEAR
  368. packet_dispatch (PACKET *pack, int port, int mode)
  369. {
  370.     NETPORT    *np;
  371.     PACKET    *outpak;
  372.     int    ret;
  373.  
  374.     np = &netports[port];
  375.     if (!(np->flags & NP_ON))
  376.         return (1);
  377.     outpak = np->outpak;
  378.     if (!pack) {
  379.         ret = 0;
  380.         if (outpak && outpak->length > 1) {
  381.             ret |= packet_xmit (outpak, np);
  382.             outpak->length = 1;    /* reuse outpak */
  383.         }
  384.         ret |= packet_xmit (pack, np);    /* flush port */
  385.         return (ret);
  386.     }
  387.     ++STATS_NETSENTP;
  388.     if (!mode || !(np->flags & NP_PACKING))
  389.         return (packet_xmit (pack, np));
  390.     if (!outpak) {
  391.         outpak = np->outpak = packet_new (np->packlen, -1);
  392.         if (!outpak)            /* sorry, no can pak */
  393.             return (packet_xmit (pack, np));
  394.         outpak->length = 1;
  395.         outpak->raw[0] = RC_PACKED;
  396.     }
  397.     if ((Uint)(pack->length + 2 + 1) > np->packlen) {
  398.         ret  = packet_xmit (outpak, np);
  399.         ret |= packet_xmit (pack, np);
  400.         return (ret);
  401.     }
  402.     if ((Uint)(pack->length + 2) > np->packlen - outpak->length) {
  403.         packet_xmit (outpak, np);
  404.         outpak->length = 1;        /* reuse outpak */
  405.     }
  406.     outpak->raw[outpak->length++] = (Uchar)(0x0ff&(pack->length >> 8));
  407.     outpak->raw[outpak->length++] = (Uchar)(0x0ff&(pack->length));
  408.     memcpy (&outpak->raw[outpak->length], pack->raw, pack->length);
  409.     outpak->length += pack->length;
  410.     return (0);
  411. }
  412.  
  413. extern int FAR
  414. packet_send (PACKET *pack, int mode)
  415. /*
  416.  * mode:
  417.  * 0 send to addressed player
  418.  * 1 broadcast to all netports
  419.  * 2 broadcast to all active netports
  420. */
  421. {
  422.     int    port, ret;
  423.  
  424.     ret = 0;
  425.     if (!pack) {
  426.         for (port = 0; port < nnetports; ++port)
  427.             ret |= packet_dispatch (pack, port, mode);
  428.     } else if (mode) {
  429.         if (st.network & NET_NOBCAST)
  430.             return (1);
  431.         pack->address = 0;    /* broadcast */
  432.         for (port = 0; port < nnetports; ++port) {
  433.             if (2 == mode && !netports[port].nplayers)
  434.                 continue;
  435.             pack->netport = port;
  436.             ret |= packet_dispatch (pack, port, mode);
  437.         }
  438.     } else
  439.         ret |= packet_dispatch (pack, pack->netport, mode);
  440.     return (ret);
  441. }
  442.  
  443. static char    FAR name[32];
  444. static char    FAR hex[4];
  445.  
  446. extern char * FAR
  447. netport_name (int port)
  448. {
  449.     sprintf (name, "%s.%c",
  450.         netports[port].NetDriver->name, (int)netports[port].unit);
  451.     return (name);
  452. }
  453.  
  454. extern char * FAR
  455. netport_addr (int port, Uchar *addr)
  456. {
  457.     int    i;
  458.  
  459.     name[0] = '\0';
  460.     for (i = 0; i < LADDRESS; ++i) {
  461.         sprintf (hex, "%02x", (int)addr[i]);
  462.         strcat (name, hex);
  463.     }
  464.  
  465.     return (name);
  466. }
  467.